#include "music.h"
#include "bsp_buzzer.h"
#include "stm32f4xx_hal.h"

// 音符频率定义
#define qdo    262
#define qre    294
#define qmi    330
#define qfa    349
#define qso    392
#define qla    440
#define qsi    494
#define do     523
#define re     578
#define mi     659
#define fa     698
#define so     784
#define la     880
#define si     988
#define do1    1046
#define re1    1175
#define mi1    1318
#define fa1    1480
#define so1    1568
#define la1    1760
#define si1    1976

// 节拍定义
#define pai 400
#define ban 200
#define quarter_pai 100 // 四分之一拍

#define NOTE_NUM 100  // 根据实际音符数量调整
static Note Notes[NOTE_NUM];  // Array of notes

static uint32_t last_note_id = 0;  // Index of the last note
static uint32_t write_id = 1;      // Index of the note to be written
static uint32_t play_id = 1;       // Index of the note to be played

static uint32_t start_time = 0;  // Start time of the music
static uint32_t now = 0;

/*-------------------- Private functions --------------------*/
static void WriteNote(int note, float Long)
{
    Notes[write_id].note = note;
    Notes[write_id].Long = Long;
    Notes[write_id].end = Notes[write_id - 1].end + Long;
    write_id++;
}

static void SleepNote(float Long) { WriteNote(0, Long); }

/*-------------------- User functions --------------------*/
void MusicBillieJeanInit(void)
{
    SleepNote(ban);  // 0 半拍
    WriteNote(fa1, ban);  // 4 半拍高
    WriteNote(fa1, ban);  // 4 半拍高
    WriteNote(fa1, ban);  // 4 半拍高
    WriteNote(fa1, ban);  // 4 半拍高
    WriteNote(mi, ban);  // 3 半拍中
    WriteNote(re, ban);  // 2 半拍中
    WriteNote(mi, ban);  // 3 半拍中
    WriteNote(mi, ban);  // 3 半拍中
    WriteNote(re, ban);  // 2 半拍中
    WriteNote(fa1, ban);  // 4 半拍高
    WriteNote(mi, quarter_pai);  // 3 四分之一拍中
    WriteNote(re, quarter_pai);  // 2 四分之一拍中
    WriteNote(mi, ban);  // 3 半拍中
    WriteNote(re, ban);  // 2 半拍中
    WriteNote(fa1, pai);  // 4 一拍高
    SleepNote(ban);  // 0 半拍
    WriteNote(fa1, ban);  // 4 半拍高
    WriteNote(fa1, ban);  // 4 半拍高
    WriteNote(fa1, ban);  // 4 半拍高
    WriteNote(fa1, ban);  // 4 半拍高
    WriteNote(mi, ban);  // 3 半拍中
    WriteNote(re, ban);  // 2 半拍中
    WriteNote(mi, ban);  // 3 半拍中
    WriteNote(re, ban);  // 2 半拍中
    WriteNote(fa1, pai);  // 4 一拍高
    WriteNote(mi, ban);  // 3 半拍中
    WriteNote(mi, ban);  // 3 半拍中
    WriteNote(re, ban);  // 2 半拍中
    WriteNote(do1, ban);  // 1 半拍高
    WriteNote(qsi, ban);  // 7 半拍低
    WriteNote(qsi, pai);  // 7 一拍低
    SleepNote(pai);  // 0 一拍
    WriteNote(qsi, quarter_pai);  // 7 四分之一拍低
    WriteNote(do1, quarter_pai);  // 1 四分之一拍高
    WriteNote(qsi, ban);  // 7 半拍低
    WriteNote(qsi, pai);  // 7 一拍低
    SleepNote(pai);  // 0 一拍
    WriteNote(qsi, quarter_pai);  // 7 四分之一拍低
    WriteNote(do1, quarter_pai);  // 1 四分之一拍高
    WriteNote(qsi, ban);  // 7 半拍低
    WriteNote(qsi, pai);  // 7 一拍低
    SleepNote(pai);  // 0 一拍
    WriteNote(qsi, quarter_pai);  // 7 四分之一拍低
    WriteNote(do1, quarter_pai);  // 1 四分之一拍高
    WriteNote(qsi, ban);  // 7 半拍低
    WriteNote(qsi, ban);  // 7 半拍
    SleepNote(pai);  // 0 一拍
    SleepNote(pai);  // 0 一拍
    SleepNote(pai);  // 0 一拍
    SleepNote(ban);  // 0 半拍

    last_note_id = write_id - 1;
    write_id = 1;
}

void MusicBillieJeanPlay(void)
{
    now = HAL_GetTick();
    if (now - start_time >= Notes[play_id].end) {
        play_id++;
        if (play_id > last_note_id) {
            play_id = 1;
            start_time = now;
        }

        buzzer_note(Notes[play_id].note, 0.07);
    }
}

    
